package cn.lyjuan.pojoutils.genclass.impl;

import cn.lyjuan.base.util.StringUtils;
import cn.lyjuan.pojoutils.bean.ColumnBean;
import cn.lyjuan.pojoutils.bean.MySQLDBTypeBean;
import cn.lyjuan.pojoutils.bean.TableBean;
import cn.lyjuan.pojoutils.genclass.ATableInfoImpl;
import cn.lyjuan.pojoutils.util.ConnUtils;
import cn.lyjuan.pojoutils.util.MySQLDBTypeUtils;

import java.sql.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by ly on 2014/11/23.
 */
public class MySQLTableInfoImpl extends ATableInfoImpl
{
    @Override
    public void parseTableInfo(TableBean tableBean, List<ColumnBean> cols) throws SQLException
    {
        PreparedStatement   ps     = null;
        ResultSet           rs     = null;
        String              sql    = "SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = '" + tableBean.getDatabase() + "' AND TABLE_NAME = '" + tableBean.getTableName() + "'";
        String              coms   = "";
        Map<String, String> comMap = new HashMap<String, String>();
        Connection          conn   = null;
        try
        {
            conn = ConnUtils.getConn(tableBean.getUrl(), tableBean.getUser(), tableBean.getPwd());
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();

            if (!rs.next())
            {
                throw new RuntimeException("have not table(" + tableBean.getTableName()
                        + ") info in db(" + tableBean.getDatabase()
                        + "), please check database url,database and tablename set.");
            }

            tableBean.setPojoComment(rs.getString("TABLE_COMMENT"));
        } finally
        {
            if (null != rs && !rs.isClosed())
                rs.close();
            if (null != ps && !ps.isClosed())
                ps.close();
            if (null != conn && !conn.isClosed())
                conn.close();
        }
    }

    @Override
    public void parseColumnInfo(TableBean tableBean, List<ColumnBean> cols) throws SQLException
    {
        String            sql  = "SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '" + tableBean.getDatabase() + "' AND table_name = '" + tableBean.getTableName() + "'";
        Connection        conn = null;
        PreparedStatement ps   = null;
        ResultSet         rs   = null;

        String name = null;
        try
        {
            conn = ConnUtils.getConn(tableBean.getUrl(), tableBean.getUser(), tableBean.getPwd());
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            while (rs.next())
            {
                name = rs.getString("COLUMN_NAME").toLowerCase();
                ColumnBean col = getCol(cols, name);
                // 类型
                col.dbTypeName = rs.getString("COLUMN_TYPE");
                // 是否主键
                if ("PRI".equals(rs.getString("COLUMN_KEY")))
                    col.isPriKey = true;
                else col.isPriKey = false;

                String extra = rs.getString("EXTRA");
                if (!StringUtils.isNull(extra) && "auto_increment".indexOf(extra.toLowerCase()) > -1)
                    col.autoInc = true;

                // 可为空
                if ("YES".equals(rs.getString("IS_NULLABLE")))
                    col.isNull = true;
                else col.isNull = false;
                // 默认值
                col.defVal = rs.getString("COLUMN_DEFAULT");
                // 注释
                col.comment = rs.getString("COLUMN_COMMENT");
            }
        } finally
        {
            if (null != rs && !rs.isClosed())
                rs.close();
            if (null != ps && !ps.isClosed())
                ps.close();
            if (null != conn && !conn.isClosed())
                conn.close();
        }

    }

    @Override
    public void parseDBType(TableBean tableBean, List<ColumnBean> cols) throws SQLException
    {
        String sql = "SELECT * FROM " + tableBean.getTableName();

        Connection        conn = null;
        PreparedStatement ps   = null;
        ResultSet         rs   = null;
        ResultSetMetaData rsmd = null;

        String          name  = null;
        ColumnBean      col   = null;
        MySQLDBTypeBean mysql = null;
        try
        {
            conn = ConnUtils.getConn(tableBean.getUrl(), tableBean.getUser(), tableBean.getPwd());
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            rsmd = rs.getMetaData();
            for (int i = 1; i <= rsmd.getColumnCount(); i++)
            {
                name = rsmd.getColumnName(i).toLowerCase();
                col = getCol(cols, name);
                col.type = rsmd.getColumnType(i);
                //col.dbTypeName = rsmd.getColumnTypeName(i);
                mysql = MySQLDBTypeUtils.getDBType(col.type);
                if (null == mysql)
                    throw new RuntimeException("unknow mysql db type: " + col.type + "(" + name + ")");
                col.typeName = mysql.typeName;
                col.mybatisJavaType = mysql.mybatisJavaType;
                col.mybatisJdbcType = mysql.mybatisJdbcType;
            }
        } finally
        {
            if (null != rs && !rs.isClosed())
                rs.close();
            if (null != ps && !ps.isClosed())
                ps.close();
            if (null != conn && !conn.isClosed())
                conn.close();
        }

    }

    /**
     * 从字段信息集合中获取字段信息，如果集合中没有，则新建，并赋于相应字段名
     *
     * @param cols   字段信息集合
     * @param column 字段名
     * @return 返回字段信息
     */
    private ColumnBean getCol(List<ColumnBean> cols, String column)
    {
        column = StringUtils.isNull(column) ? "" : column.toLowerCase();
        for (ColumnBean c : cols)
        {
            if (c.column.equals(column))
                return c;
        }

        // 不存在则创建
        ColumnBean col = null;
        col = new ColumnBean();
        col.column = column;
        cols.add(col);
        return col;
    }

    @Override
    public void parseSequence(TableBean tableBean, List<ColumnBean> cols)
    {
        // MySQL no Sequence
    }
}
